
/**********************************************************************************\
** 文件名称: menu.c
** 创建人员: YCG
** 创建日期: 2018-11-22
** 文档描述: 本文键只是大致将各功能区分开来，各函数之间是紧密联系的。
** 版本代号: V0.1
** 版本说明: 初始版本
\********************************************************************************/
#include	"menu.h"

u8 volatile min, min_h, min_l, hour, hour_h, hour_l; //用来保存分钟与小时
u8 volatile sec;                     //用来上一次的秒数
bit led_point = 0;          //外围整点标记
bit sec_update_flag = 0;    //秒更新标记
bit show_update_flag = 0;   //秒更新标记

/*******************************************************************************
** 函数名称: MainInit
** 功能描述:
** 参数说明: None
** 返回说明: None
** 创建人员: YCG
** 创建日期: 2018-11-22
********************************************************************************/
void MainInit(void) {
    delay(500);
    if(KeyRead(KEY_MENU, KEY_SHORT)) {}    //清除所有的键值，防止误触发
    if(KeyRead(KEY_MENU, KEY_LONG)) {}
    if(KeyRead(KEY_ADD, KEY_SHORT)) {}
    if(KeyRead(KEY_ADD, KEY_LONG)) {}

    SetPoint(1);                      //小数点闪烁
    SetCubeBlink(0);                  //将数码管设置为不闪烁
    ResetSystime();                   //清空定时器ms计时
}

/*******************************************************************************
** 函数名称: MainUpdate
** 功能描述: 从DS1302更新系统的时间显示，每秒更新一次
							只有菜单值为零时才更新
** 参数说明: None
** 返回说明: None
** 创建人员: YCG
** 创建日期: 2018-11-22
********************************************************************************/
void MainUpdate(void) {
    if(GetSystime() > 990) {       //只有定时器计时达到990ms以上是才读取秒数有没有改变,避免一直读秒
        if(sec != DsReadReg(SEC)) { //判断秒数有没有更新
            sec = DsReadReg(SEC);       //更新秒
            sec = 10 * ((sec >> 4)&B0000_0111) + (sec & B0000_1111);  //计算出十进制的秒数

            sec_update_flag = 1;       //设置1s更新标记
            show_update_flag = 1;      //更新数码管显示数据

            ResetSystime();           //清空定时器ms计时
					
                min  = DsReadReg(MIN);           //读取分钟时间
                min_l =  min & B0000_1111;       //获取分钟低位
                min_h = (min >> 4)&B0000_0111;   //获取分钟高位
                hour = DsReadReg(HOUR);          //读取小时
                hour_l =  hour    & B0000_1111;  //获取小时低位
                hour_h = (hour >> 4)&B0000_0011; //获取小时高位
        }
    }
}

/*******************************************************************************
** 函数名称: MainShow
** 功能描述: 将数据显示到数码管，只有更新标记出现时才会更新
** 参数说明: None
** 返回说明: None
** 创建人员: YCG
** 创建日期: 2018-11-22
********************************************************************************/
void MainShow(void) {
    if(show_update_flag) {
        SetCube(hour_h, 0);           //设置数码管显示
        SetCube(hour_l, 1);
        SetCube(min_h,  2);
        SetCube(min_l,  3);
        show_update_flag = 0;        //将标记清零
    }
}

/*******************************************************************************
** 函数名称: MainMune
** 功能描述: 菜单值管理，一共有五个菜单，每次菜单键按下都会更新值，并刷新数码管显示模式
** 参数说明: mode_num: [输入/出]  系统的菜单值，
** 返回说明: None
** 创建人员: YCG
** 创建日期: 2018-11-22
********************************************************************************/
void MainKeyMenu(u8* menu) {
    if(KeyRead(KEY_MENU, KEY_LONG))  //读取菜单键短按
    {
        if(*menu == 0) { //菜单值为零时
            DsSetTime(SEC, 0x00);  //清空秒
        } else { //不为零则将菜单值设为零
            *menu = 0;
            SetPoint(1);                      //小数点闪烁
            SetCubeBlink(0);                 //将数码管设置为不闪烁
        }
    }
    /**********菜单键的扫描以及执行对应的程序**********/
    if(KeyRead(KEY_MENU, KEY_SHORT))  //读取菜单键短按
    {
        if(++*menu >= MENU_MAX) *menu = 0; //菜单只有五个

        /**********菜单键按下后执行一次的程序**********/
        switch(*menu) {  //用来处理五级菜单对应功能
        case MENU_SHOW :        //正常显示模式
            SetPoint(1);                      //小数点闪烁
            SetCubeBlink(0);                 //将数码管设置为不闪烁
            break;
        case MENU_SET_MIN_L :     //设置分钟个位模式
            SetPoint(0);                     //小数点不闪烁
            SetCubeBlink(4);                 //将分钟个位设置为闪烁
            break;
        case MENU_SET_MIN_H :     //设置分钟十位模式
            SetPoint(0);                     //小数点不闪烁
            SetCubeBlink(3);                 //将分钟十位设置为闪烁
            break;
        case MENU_SET_HOUR_L :     //设置小时个位模式
            SetPoint(0);                     //小数点不闪烁
            SetCubeBlink(2);                 //将小时个位设置为闪烁
            break;
        case MENU_SET_HOUR_H :     //设置小时十位模式
            SetPoint(0);                     //小数点不闪烁
            SetCubeBlink(1);                 //将小时十位设置为闪烁
            break;
        }
    }

}
/*******************************************************************************
** 函数名称: MainKeyAdd
** 功能描述: 每级菜单下增加键对应的功能
							 短按：
										 模式0：切换显示模式
										 模式1-4：增加所对应的时间，并且刷新显示
							 长按：
										 打开关闭整点显示
** 参数说明: mode: [输入/出]  Led显示模式的设置
**			     menu: [输入]     输入当前的菜单值
** 返回说明: None
** 创建人员: YCG
** 创建日期: 2018-11-22
********************************************************************************/
void MainKeyAdd(u8 * mode, u8 menu) {

    if(KeyRead(KEY_ADD, KEY_LONG))   //读取增加键长按
    {
        led_point = ~led_point;       //打开关闭整点显示
    }

    if(KeyRead(KEY_ADD, KEY_SHORT))   //读取 增加键 短按
    {
        switch(menu) {   //用来处理五级菜单对应功能

        case MENU_SHOW :     //正常显示模式
            if(++*mode > LED_MODE_MAX - 1)  *mode = 0;    //外围灯的显示模式
            break;

        case MENU_SET_MIN_L :     //设置分钟个位模式
            if(++min_l > 9) min_l = 0;             //个位只有0-9
            DsSetTime(MIN, (min & B1111_0000) | min_l);	//每次都会将时间写入芯片
            break;

        case MENU_SET_MIN_H :     //设置分钟十位模式
            if(++min_h > 5) min_h = 0;             //十位只有0-5
            DsSetTime(MIN, (min & B1000_1111) | (min_h << 4));	//每次都会将时间写入芯片
            break;

        case MENU_SET_HOUR_L :     //设置小时个位模式
            if(hour_h < 2) {
                if(++hour_l > 9) hour_l = 0;               //个位只有0-9
            } else {
                if(++hour_l > 3) hour_l = 0;               //个位只有0-9
            }
            DsSetTime(HOUR, (hour & B1111_0000) | hour_l);	//每次都会将时间写入芯片
            break;

        case MENU_SET_HOUR_H :     //设置小时十位模式
            if(++hour_h > 2) hour_h = 0;             //十位只有0-2
            DsSetTime(HOUR, (hour & B1000_1111) | (hour_h << 4) );	//每次都会将时间写入芯片
            break;
        }
        show_update_flag = 1; //增加键按下一定会更新显示
    }
}

/*******************************************************************************
** 函数名称: MainLedMode
** 功能描述: 外围灯显示模式，定义外围灯的功能主要在这里
** 参数说明: mode：输入当前的显示模式
** 返回说明: None
** 创建人员: YCG
** 创建日期: 2018-11-22
********************************************************************************/
void MainLedMode(u8 mode) {
    static  u16 led_show_time = 0;  //LED模式显示计时
    static u8 led_show_num = 0;             //LED显示计数
    u8 led_num = 0;                 //外围灯0-59扫描计数
    switch(mode) {

    case 0 :         //模式0:显示秒点与整点
        for(led_num = 0; led_num < 60; led_num++) {
            if(led_num == sec || (led_point && (led_num % 5 == LED_POINT))) //选择秒点与整点
            {
                SetLedBit(led_num);	   //打开灯
            } else {
                ResetLedBit(led_num);  //关闭灯
            }
        }
        break;
				
    case 1 :         //模式1:点亮小于等于秒对应的灯
        for(led_num = 0; led_num < 60; led_num++) {
            if(led_num <= sec || (led_point && (led_num % 5 == LED_POINT)))
            {
                SetLedBit(led_num);	   //打开灯
            } else {
                ResetLedBit(led_num);  //关闭灯
            }
        }
        break;

    case 2 :          //模式2:1灯流水模式
        if(sec_update_flag == 1) {
            sec_update_flag = 0;
            if(led_point)  led_show_num = sec;       //亮的灯
            else             led_show_num = 59;       //亮的灯
            led_show_time = 0;
        }
        if(GetSystime() >= led_show_time) {  //按照流过灯的数量将时间进行等分
            if(led_point) led_show_time += 1000 / sec; //计算下一次的时间
            else  led_show_time += 1000 / 59;
            led_show_num--;             //每次到达时间
        }

        for(led_num = 0; led_num < 60; led_num++) {
            if((led_num > sec && led_point) || led_num == led_show_num)
            {
                SetLedBit(led_num);	   //打开灯
            } else {
                ResetLedBit(led_num);  //关闭灯
            }
        }
        break;

    case 3 :          //模式3:2灯流水模式
        if(sec_update_flag == 1) {
            sec_update_flag = 0;
            led_show_num = 0;        //亮的灯
            led_show_time = 0;
        }
        if(GetSystime() >= led_show_time) {  //按照流过灯的数量将时间进行等分
            led_show_time += 1000 / 30; //计算下一次的时间
            led_show_num++;             //每次到达时间
        }

        for(led_num = 0; led_num < 60; led_num++) {
            if(!led_point) {
                if((led_num == led_show_num - 1) || led_num == 60 - led_show_num)
                {
                    SetLedBit(led_num);	   //打开灯
                } else {
                    ResetLedBit(led_num);  //关闭灯
                }
            } else {
                if((led_num <= led_show_num - 1) || led_num >= 60 - led_show_num)
                {
                    SetLedBit(led_num);	   //打开灯
                } else {
                    ResetLedBit(led_num);  //关闭灯
                }
            }
        }
        break;


    case 4:           //12灯旋转模式
        if(sec_update_flag == 1) {
            sec_update_flag = 0;
            led_show_num = 0;        //亮的灯
            led_show_time = 0;
        }
        if(GetSystime() >= led_show_time) {  //按照流过灯的数量将时间进行等分
            if(!led_point) {
                led_show_time += 1000 / 5; //计算下一次的时间
            } else {
                led_show_time += 1000 / 20; //计算下一次的时间
            }
            led_show_num = ++led_show_num % 5;         //每次到达时间
        }

        for(led_num = 0; led_num < 60; led_num++) {
            if(led_num % 5 == led_show_num)
            {
                SetLedBit(led_num);	   //打开灯
            } else {
                ResetLedBit(led_num);  //关闭灯
            }
        }

        break;


    case 5:           //4灯旋转模式
        if(sec_update_flag == 1) {
            sec_update_flag = 0;
            led_show_num = 255;        //亮的灯
            led_show_time = 0;
        }
        if(GetSystime() >= led_show_time) {  //按照流过灯的数量将时间进行等分
            led_show_time += 1000 / 30; //计算下一次的时间
            if(GetSystime() <= 500) {
                ++led_show_num;      //每次到达时间
            } else {
                --led_show_num;
            }
        }
        for(led_num = 0; led_num < 60; led_num++) {
            if(!led_point) {
                if(led_num % 15 == led_show_num)
                {
                    SetLedBit(led_num);	   //打开灯
                } else {
                    ResetLedBit(led_num);  //关闭灯
                }
            } else {
                if(led_num % 15 <= led_show_num)
                {
                    SetLedBit(led_num);	   //打开灯
                } else {
                    ResetLedBit(led_num);  //关闭灯
                }
            }
        }

        break;

    case 6:           //12灯旋转模式
        if(sec_update_flag == 1) {
            sec_update_flag = 0;
            led_show_num = 255;        //亮的灯
            led_show_time = 0;
        }

        if(GetSystime() >= led_show_time) {  //按照流过灯的数量将时间进行等分

            led_show_time += 1000 / 30; //计算下一次的时间
            if(GetSystime() <= 500) {
                ++led_show_num;      //每次到达时间
            } else {
                --led_show_num;
            }
            //  led_show_num = ++led_show_num % 15;      //每次到达时间
        }

        for(led_num = 0; led_num < 60; led_num++) {
            if(!led_point) {
                if(led_num == led_show_num \
                        || (led_num == 30 - led_show_num) \
                        || (led_num == 30 + led_show_num) \
                        || (led_num == 59 - led_show_num))
                {
                    SetLedBit(led_num);	   //打开灯
                } else {
                    ResetLedBit(led_num);  //关闭灯
                }
            } else {
                if(led_num <= led_show_num \
                        || ((led_num >= 30 - led_show_num) && (led_num <= 30)) \
                        || ((led_num <= 30 + led_show_num) && (led_num >= 30)) \
                        || (led_num >= 59 - led_show_num))
                {
                    SetLedBit(led_num);	   //打开灯
                } else {
                    ResetLedBit(led_num);  //关闭灯
                }
            }
        }
        break;

    case 7:           //12灯旋转模式
        if(sec_update_flag == 1) {
            sec_update_flag = 0;
            led_show_num = 255;        //亮的灯
            led_show_time = 0;
        }

        if(GetSystime() >= led_show_time) {  //按照流过灯的数量将时间进行等分

            led_show_time += 1000 / 30; //计算下一次的时间
            if(GetSystime() <= 500) {
                ++led_show_num;      //每次到达时间
            } else {
                --led_show_num;
            }
            //  led_show_num = ++led_show_num % 15;      //每次到达时间
        }

        for(led_num = 0; led_num < 60; led_num++) {
            if(!led_point) {
                if(led_num <= led_show_num \
                        || (led_num == 30 - led_show_num) \
                        || (led_num == 30 + led_show_num) \
                        || (led_num >= 59 - led_show_num))
                {
                    SetLedBit(led_num);	   //打开灯
                } else {
                    ResetLedBit(led_num);  //关闭灯
                }
            } else {
                if(led_num <= led_show_num \
                        || ((led_num <= 30 - led_show_num) && (led_num >= 15)) \
                        || ((led_num >= 30 + led_show_num) && (led_num <= 45)) \
                        || (led_num >= 59 - led_show_num))
                {
                    SetLedBit(led_num);	   //打开灯
                } else {
                    ResetLedBit(led_num);  //关闭灯
                }
            }
        }
        break;
    }
}
/********************************End of File************************************/
